home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / maxshell101.lha / MAXShell.c < prev    next >
C/C++ Source or Header  |  1995-09-14  |  26KB  |  996 lines

  1. /*
  2.    MAXShell v1.01 - A door for running CLI based programs under M A X's BBS
  3.    ~~~~~~~~~~~~~~
  4.    Based on TrShell, by Timothy Aston. Max's adaption by MPS '95!
  5.  
  6.    See MAXShell.DOC for information on using this program.
  7. */
  8.  
  9. const char version[]="\0$VER: MAXShell 1.01 ("__DATE__")\0";
  10.  
  11. #include <clib/exec_protos.h>
  12. #include <exec/exec.h>
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <exec/ports.h>
  16. #include <exec/libraries.h>
  17. #include <fcntl.h>
  18. #include <libraries/dos.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "fifo.h"
  23. #include "fifopr.h"
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <time.h>
  27.  
  28. #define ESC 27
  29. #define FF 12
  30.  
  31. char StrOut[255]; /* Output String! */
  32.  
  33. struct Library *FifoBase=NULL;
  34. struct MsgPort *fifoport;
  35. void *fifoR=NULL, *fifoW=NULL;
  36. struct Message rmsg,wmsg;
  37.  
  38. char fifoname[30]="12345678901234567890123456789"; /* Name of FIFO */
  39. char commandline[80]="NewShell FIFO:";
  40.                       /* Command line for opening a FIFO: redirected CLI */
  41. char newfile[30]="";
  42.                       /* Filename for autoinsert-converted shell-startup */
  43. char newchar=' ';     /* Character used to replace spaces in user name */
  44. char charbuf[100],txt[255];
  45. char *fifoslav,*fifomast;
  46. BOOL quit=FALSE;
  47. BOOL readpending=FALSE, writepending=FALSE;
  48. LONG n;
  49.  
  50. BOOL filterc=FALSE, filterd=FALSE, filtere=FALSE, filterf=FALSE, lesstime=FALSE;
  51.  
  52. void setup_fifo(void);
  53. void shell_loop(void);
  54. void Out(char *);
  55. int InChar(void);
  56. void SendBreak(char);
  57. void check_fifo(void);
  58. void OutLen(char * , ULONG);
  59. void convert_lf(char * , char * , LONG);
  60. void show_usage(void);
  61. void close_all(void);
  62.  
  63. long getuserint(int);
  64. void checkkey(char *);
  65. void GetAutoInsert(char, char *);
  66.  
  67. void end(void);
  68. void getsvar(int, char *);
  69. void sendmessage(char[], int);
  70. void hotkey(char[], char *);
  71. void prompt(char[], char *, int);
  72. void showfile(char[]);
  73. void domenu(int, int, char *);
  74. void changeuserint(int, long);
  75.  
  76. struct DoorMsg {
  77.     struct Message Door_Msg;
  78.     short command;
  79.     short data;
  80.     char string[80];
  81.     short carrier;
  82.     };
  83.  
  84. struct DoorMsg *doormsg, *garbage;
  85. struct MsgPort *MyPort, *replyport;
  86.  
  87. struct Task *mytask; /* Pointer to this task so we can name it */
  88.  
  89. int err;
  90.  
  91. char linebuf[3000]=""; /* Line buffer */
  92.  
  93. time_t timeval;   /* So we can get the time (For a different FIFO  name    */
  94. time_t *timeptr; /* every time the door is run (Avoiding the closing bug) */
  95.  
  96. FILE *ifp, *ofp, *fopen();
  97.  
  98. /* FILE *ofp2; */
  99.  
  100. /*
  101.  * end() -  Notifies Paragon that we are done and ready to continue with
  102.  *        the BBS.  ALWAYS use this to exit from your program, or
  103.  *        the BBS will go to never-never land.
  104.  */
  105.  
  106. void end(void)
  107. {
  108.     doormsg->command = 20;
  109.     PutMsg(MyPort,(struct Message *)doormsg);
  110.     (void)WaitPort(replyport);
  111.     (void)GetMsg(replyport);
  112.     FreeMem(doormsg,(long)sizeof(*doormsg));
  113.     DeletePort(replyport);
  114.     exit(0);
  115. }
  116.  
  117. /*
  118.  * getsvar(typ,mstring) - Gets certain string variables from Paragon.
  119.  * "mstring" is a pointer to a string to dump the string into.  "typ" tells
  120.  * it what you want: 1=Name, 2=Password, 3=Address, 4=City, 5=State
  121.  * 6=Postal code, 7=Door pathname, 8=Default BBS pathname.
  122.  */
  123.  
  124. /* Extra Max's values:                 9: Date
  125.                                        10: Time
  126.                                        100: Phone number
  127.                                        101: Computer type
  128.                                        102: Comment (as defined by Sysop) */
  129.  
  130. void getsvar(typ,mstring)
  131. int typ;
  132. char *mstring;
  133. {
  134.     doormsg->data = typ;
  135.     doormsg->command = 14;
  136.     PutMsg(MyPort,(struct Message *)doormsg);
  137.     (void)WaitPort(replyport);
  138.     strcpy(mstring,doormsg->string);
  139.     (void)GetMsg(replyport);
  140. }
  141.  
  142. /*
  143.  * sendmessage(mstring,nl) - Sends a message to the local window and to
  144.  * the modem (if applicable).  "mstring" is the output string you want to
  145.  * send, "nl" is an integer which is 1 if you want it to send the
  146.  * c/r+l/f combination, or 0 if not.
  147.  */
  148.  
  149. void
  150. sendmessage(mstring,nl)
  151. char mstring[];
  152. int nl;
  153. {
  154. char newstr[100];
  155. int i, ii=0;
  156.  
  157. if (doormsg->carrier==1) return; /* Make sure no output is attempted if
  158.                                         carrier lost */
  159.     doormsg->data = nl;
  160.     doormsg->command = 1;
  161.  
  162. /* Strip out some escape codes unsupported by Max's. What do they do anyway?
  163.    This INCREDIBLY sloppy code just makes things like Contris and Vampire's
  164.    Castle look better rather than having strange [ p's, etc. showing up) */
  165.  
  166. for(i=0; i<strlen(mstring); i++)
  167. {
  168.         newstr[ii]=mstring[i];
  169.         if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+3]==' '
  170.                                    && mstring[i+4]=='p')
  171.         {
  172.                 ii--;
  173.                 i+=4;
  174.         }
  175.         else if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+2]==' '
  176.                                    && mstring[i+3]=='p')
  177.         {
  178.                 ii--;
  179.                 i+=3;
  180.         }
  181.         else if(newstr[ii]=='\033' && mstring[i+1]=='\033' && mstring[i+2]=='['
  182.                                    && mstring[i+3]==' ' && mstring[i+4]=='p')
  183.         {
  184.                 ii--;
  185.                 i+=4;
  186.         }
  187.         else if(newstr[ii]=='\033' && mstring[i+1]=='\033' && mstring[i+2]=='['
  188.                                    && mstring[i+4]==' ' && mstring[i+5]=='p')
  189.         {
  190.                 ii--;
  191.                 i+=5;
  192.         }
  193.         else if(newstr[ii]=='\233' && mstring[i+1]==' ' && mstring[i+2]=='p')
  194.         {
  195.                 ii--;
  196.                 i+=3;
  197.         }
  198.         else if(newstr[ii]=='\233' && mstring[i+1]=='0' && mstring[i+2]==' '
  199.                                                         && mstring[i+3]=='p')
  200.         {
  201.                 ii--;
  202.                 i+=4;
  203.         }
  204. /*        else if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+5]=='f')
  205.         {
  206.                 ii--;
  207.                 i+=6;
  208.         }
  209.         else if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+6]=='f')
  210.         {
  211.                 ii--;
  212.                 i+=7;
  213.         }
  214.         else if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+7]=='f')
  215.         {
  216.                 ii--;
  217.                 i+=8;
  218.         } */
  219.         ii++;
  220. }
  221.         newstr[ii]='\0';
  222.         strcpy(doormsg->string,"");
  223.         PutMsg(MyPort,(struct Message *)doormsg);
  224.     (void)WaitPort(replyport);
  225.     (void)GetMsg(replyport);
  226.         if(newstr[0]!='\0')
  227.         {
  228.             strcpy(doormsg->string,newstr);
  229.                 PutMsg(MyPort,(struct Message *)doormsg);
  230.             (void)WaitPort(replyport);
  231.             (void)GetMsg(replyport);
  232.         }
  233.     strcpy(doormsg->string,"");
  234.         PutMsg(MyPort,(struct Message *)doormsg);
  235.     (void)WaitPort(replyport);
  236.     (void)GetMsg(replyport);
  237. /*         fprintf(ofp2, "<-%s", newstr);   */
  238. }
  239.  
  240. /*
  241.  * hotkey(mstring,ostring) - outputs the string "mstring" and waits
  242.  * for one key which it will place in element [0] of "ostring".
  243.  * "mstring" may be a null string, in which case it will only wait for
  244.  * the key, and not output any prompt.
  245.  */
  246.  
  247. void
  248. hotkey(mstring,ostring)
  249. char mstring[];
  250. char *ostring;
  251. {
  252.     strcpy(doormsg->string,mstring);
  253.     doormsg->command = 8;
  254.     PutMsg(MyPort,(struct Message *)doormsg);
  255.     (void)WaitPort(replyport);
  256.     (void)GetMsg(replyport);
  257.     strcpy(ostring,doormsg->string);
  258. }
  259.  
  260. /*
  261.  * prompt(mstring,ostring,len) - outputs the string "mstring" and inputs
  262.  * a string which is placed in ostring.  'len' is the maximum number of
  263.  * characters which will be accepted.
  264.  */
  265.  
  266. void
  267. prompt(mstring,ostring,len)
  268. char mstring[];
  269. char *ostring;
  270. int len;
  271. {
  272.     strcpy(doormsg->string,mstring);
  273.     doormsg->data=len;
  274.     doormsg->command = 6;
  275.     PutMsg(MyPort,(struct Message *)doormsg);
  276.     (void)WaitPort(replyport);
  277.     (void)GetMsg(replyport);
  278.     strcpy(ostring,doormsg->string);
  279. }
  280.  
  281.  
  282. /* showfile(mstring) shows the text file which mstring is the path to.
  283.    It handles ^C aborting, and ^S/^Q pausing. */
  284.  
  285. void
  286. showfile(mstring)
  287. char mstring[];
  288. {
  289.     strcpy(doormsg->string,mstring);
  290.     doormsg->command = 10;
  291.     PutMsg(MyPort,(struct Message *)doormsg);
  292.     (void)WaitPort(replyport);
  293.     (void)GetMsg(replyport);
  294. }
  295.  
  296. /****************************************************
  297.     These two functions were added by
  298.          SWhite. MAX's BBS only!
  299. ****************************************************/
  300. /* enter a menu function to execute 1-33 */
  301. void
  302. domenu(menu,extra,filename)
  303. int menu,extra;
  304. char *filename;
  305.  {
  306.     strcpy(doormsg->string,filename);
  307.     doormsg->command = menu+100;
  308.     doormsg->data     = extra;
  309.     PutMsg(MyPort,(struct Message *)doormsg);
  310.     (void)WaitPort(replyport);
  311.     (void)GetMsg(replyport);
  312. }
  313.  
  314. /* Change user information 1-15:
  315.  
  316.    0      NextEventMinutes
  317.    1       UserTimeRemaining
  318.    2      AccessLevel
  319.    3      TimeLeft
  320.    4      DL Ratio
  321.    5      Last Message Read
  322.    6      PageLength
  323.    7      NumCalls
  324.    8      UserMessages #
  325.    9      UserUpped Files
  326.    10     UserDownedFiles
  327.    11     LastDayOn
  328.    12     Last Minute On
  329.    13     UserConfig Flags                ;Lower 2 Bytes
  330.  
  331.                   Flags, bits: 0-Rd, 1-Wr, 2-Up, 3-Dn, 4-Bltn, 5-ANSI
  332.                                6-FSE, 7-Pause, 8-Cls, 9-Lck, 10-Get file
  333.                                description, 11-Junk mail, 12-Allow File
  334.                                Attaches
  335.    14     UserTimeBank
  336.    15     XFer Protocol
  337.    16     MaxTimeBank
  338. */
  339.  
  340. void
  341. changeuserint(number,val)
  342. int number;
  343. long val;
  344.  {
  345.     long *ptr;
  346.  
  347.     ptr = (long *)&doormsg->string;    /* We need a long value not a ptr */
  348.     *ptr = val;
  349.     
  350.     doormsg->command = 200;
  351.     doormsg->data    = number;
  352.     PutMsg(MyPort,(struct Message *)doormsg);
  353.     (void)WaitPort(replyport);
  354.     (void)GetMsg(replyport);
  355.  }
  356.  
  357. /* Get a piece of the user's integer information:
  358.  
  359.                 1:  Access Level
  360.                 2:  Expert mode?  (Paragon)
  361.                 3:  Net Credits?  (paragon)
  362.                 4:  Number of calls
  363.                 5:  Calls to system
  364.                 6:  Graphics mode
  365.                 7:  Minutes remaining
  366.                 8:  Screen columns
  367.                 9:  Screen rows
  368.               100:  Daily time limit
  369.               101:  File ratio
  370.               102:  Last message read (Updated when user logs off)
  371.               103:  Messages posted
  372.               104:  Files uploaded
  373.               105:  Files downloaded
  374.               106:  ?
  375.               107:  ?
  376.               108:  Flags (Binary bits)
  377.          +--------+------------+--------+---------------+ 
  378.          |  FLAG  |  VALUE     |  FLAG  |  VALUE        |  Examples
  379.          +--------+------------+--------+---------------+  ~~~~~~~~
  380.          |  Read  |  1 (2^0)   |  Pause |  128  (2^7)   | ALL ON      : 8191 
  381.          |  Write |  2 (2^1)   |  CLS   |  256  (2^8)   | ALL OFF     : 0
  382.          |  Upld  |  4 (2^2)   |  Lock  |  512  (2^9)   | Upld + Dnld : 12  
  383.          |  Dnld  |  8 (2^3)   |  GFD   |  1024 (2^10)  | ANSI + FSE  : 96
  384.          |  Bltn  | 16 (2^4)   |  Junk  |  2048 (2^11)  |
  385.          |  ANSI  | 32 (2^5)   |  AFA   |  4096 (2^13)  |
  386.          |  FSE   | 64 (2^6)   |        |               |
  387.          +--------+------------+--------+---------------+
  388.               109:  Amount in time bank
  389.               110:  Protocol
  390.               111:  Max time bank
  391. */
  392.  
  393. long getuserint(int val)
  394. {
  395.    doormsg->command=13;
  396.    doormsg->data=val;
  397.    PutMsg(MyPort,(struct Message *)doormsg);
  398.    (void)WaitPort(replyport);
  399.    (void)GetMsg(replyport);
  400.    return(doormsg->data);
  401. }
  402.  
  403. /* Check for a key, without any waiting or prompting */
  404.  
  405. void CheckKey(char *ostring)
  406. {
  407.    doormsg->command = 201;
  408.    PutMsg(MyPort,(struct Message *)doormsg);
  409.    (void)WaitPort(replyport);
  410.    (void)GetMsg(replyport);
  411.    strcpy(ostring,doormsg->string);
  412. }
  413.  
  414. /* Return Max's auto insert (And also replace spaces with defined
  415.    substitution character, in the full user name, if applicable) */
  416.  
  417. void GetAutoInsert(char istring, char *ostring)
  418. {
  419. int i;
  420.    doormsg->command = 203;
  421.    doormsg->data = istring;
  422.    PutMsg(MyPort,(struct Message *)doormsg);
  423.    (void)WaitPort(replyport);
  424.    (void)GetMsg(replyport);
  425.    strcpy(ostring,doormsg->string);
  426.    if(istring=='f')
  427.    {
  428.       for(i=0;i<strlen(ostring);i++)
  429.       {
  430.          if(ostring[i]==' ')
  431.          {
  432.             ostring[i]=newchar;
  433.          }
  434.       }
  435.    }
  436.    if(istring=='k' && lesstime==TRUE)
  437.    {
  438.       i=atoi(ostring);
  439.       i-=5;
  440.       if(i<0) i=0;
  441.       sprintf(ostring, "%d", i);
  442.    }
  443. }
  444.  
  445. /* Setup FIFO, requires Dillon's fifo.library.
  446.  */
  447. void setup_fifo()
  448. {
  449.     fifoslav = (char *) malloc(strlen(fifoname) + 16);
  450.     fifomast = (char *) malloc(strlen(fifoname) + 16);
  451.     sprintf(fifomast, "%s_m", fifoname);
  452.     sprintf(fifoslav, "%s_s", fifoname);
  453.     
  454.     fifoport=CreatePort(NULL,0L);
  455.  
  456.     fifoW = OpenFifo(fifomast, 2048, FIFOF_WRITE|FIFOF_NORMAL|FIFOF_NBIO);
  457.     if (fifoW == NULL)
  458.     {
  459.         printf("ERROR: Unable to open fifo %s\n", fifomast);
  460.  
  461. /* Temporary: I'll have to change this... */
  462.  
  463.         exit(10);
  464.     }
  465.     fifoR = OpenFifo(fifoslav, 2048, FIFOF_READ|FIFOF_NORMAL|FIFOF_NBIO);
  466.     if (fifoR == NULL)
  467.     {
  468.         printf("ERROR: Unable to open fifo %s\n", fifoslav);
  469.  
  470. /* Temporary: I'll have to change this... */
  471.  
  472.         exit(10);
  473.     }
  474.  
  475.     rmsg.mn_ReplyPort = fifoport;
  476.     wmsg.mn_ReplyPort = fifoport;
  477. }
  478.  
  479. /* The main shell loop.
  480.  */
  481. void shell_loop(void)
  482. {
  483.     char c;
  484.     char outstr[100];
  485.  
  486.         sprintf(outstr, "\r\nMAXShell v1.01\n\r\n");
  487.     Out(outstr);
  488.     
  489.     RequestFifo(fifoR,&rmsg,FREQ_RPEND);
  490.     readpending=TRUE;
  491.     
  492.     while (quit==FALSE)
  493.     {       
  494.         c=InChar();
  495.         switch ( (int) c)
  496.         {
  497.             case 3:
  498.                                 if(filterc==FALSE) SendBreak('C');
  499.                 break;
  500.             case 4:
  501.                 if(filterd==FALSE) SendBreak('D');
  502.                 break;
  503.             case 5:
  504.                 if(filtere==FALSE) SendBreak('E');
  505.                 break;
  506.             case 6:
  507.                 if(filterf==FALSE) SendBreak('F');
  508.                 break;
  509.             default:
  510.                 n=WriteFifo(fifoW,&c,1);
  511.                 if (n<1)
  512.                 {
  513.                     if (writepending==FALSE)
  514.                     {
  515.                         RequestFifo(fifoW,&wmsg,FREQ_RPEND);
  516.                         writepending=TRUE;
  517.                     }
  518.                 }
  519.                 break;
  520.         }
  521.     };
  522.         sendmessage(charbuf, 0);  /* Flush the character buffer */
  523.     n=WriteFifo(fifoW,"\r",1);
  524.     if (n<1)
  525.     {
  526.         if (writepending==FALSE)
  527.         {
  528.             RequestFifo(fifoW,&wmsg,FREQ_RPEND);
  529.             writepending=TRUE;
  530.         }
  531.     }
  532. }
  533.  
  534.  
  535. /* Get a character, complete with carrier checks and rudimentry idle timer
  536.  * checking.  Serial routines are smart enough to know whether or not 
  537.  * serial I/O should place or not, so there's no need to check if this is
  538.  * a local logon or anything like that.
  539.  */
  540. int InChar()
  541. {
  542.     ULONG l;
  543.  
  544.     for (;;)
  545.     {
  546.  
  547.            CheckKey(StrOut);
  548.            l=StrOut[0];
  549.         if (l)
  550.             return(StrOut[0]);
  551.  
  552.         if (doormsg->carrier==1)
  553.         {
  554.             sprintf(txt,"%c[0;31m%cCarrier Lost.%c[37m\r\n",ESC,FF,ESC);
  555.                         Out(txt);
  556.             SendBreak('C'); 
  557.             quit=TRUE;
  558.             return(0);
  559.         }
  560.  
  561.         /* See if anything has come from out FIFO
  562.          */
  563.         check_fifo();
  564.         if (quit==TRUE)
  565.             return(0);
  566.     
  567.  
  568. /* Fix this crap later... (Don't think it's needed for Max's anyway!) */
  569.  
  570. /*
  571.         WaitTOF();
  572.         t++;
  573.         if (t>100000)
  574.         {
  575.             sprintf(txt,"%c[0;31m%cInactivity timeout.%c[37m\r\n",ESC,FF,ESC); Out(txt);
  576.             quit=TRUE;
  577.             SendBreak('C');
  578.             return(0);
  579.         }
  580. */
  581.     }
  582. }
  583.  
  584. /* Check for something from FIFO.
  585.  */
  586. void check_fifo()
  587. {
  588.     struct Message *msg;
  589.     char *ptr;
  590.  
  591.     msg=GetMsg(fifoport);
  592.  
  593.     if (msg==(struct Message *)&rmsg)
  594.     {
  595.         readpending=FALSE;
  596.         n=ReadFifo(fifoR,&ptr,0);
  597.         if (n>0)
  598.         {
  599.  
  600. /* These 2 values were 256, but changed them to this lower value to stop
  601.    the program crashing (DoorMsg struct has room for only 80 characters) */
  602.  
  603.             if (n>40)
  604.                 n=40;
  605.             OutLen(ptr,n);
  606.             n=ReadFifo(fifoR,&ptr,n);
  607.         }
  608.         if (n<0)
  609.             quit=TRUE;
  610.         else
  611.         {
  612.             RequestFifo(fifoR,&rmsg,FREQ_RPEND);
  613.             readpending=TRUE;
  614.         }
  615.     }
  616.     else if (msg==(struct Message *)&wmsg)
  617.         writepending=FALSE;
  618. }
  619.  
  620. /* Text output to the serial device and the terminal window.  The serial
  621.  * routines are smart enough to know whether serial I/O should take place 
  622.  * or not, so its perfectly safe to always call them like this.
  623.  */
  624. void Out(char *str)
  625. {
  626.     char temp[3000];
  627.     convert_lf(temp,str,strlen(str));
  628.         sendmessage(temp, 0);
  629. }
  630.  
  631. void OutLen(char *str, ULONG len)
  632. {
  633.         int counter, counter2, newlen, escape;
  634.     char temp[3000];
  635.  
  636.         convert_lf(temp,str,len);
  637.  
  638. /* Check for a partial escape sequence at the end of the string, and save
  639.    it for the start of the next string, if required */
  640.  
  641.         newlen=strlen(temp);
  642.         counter=newlen;
  643.         escape=FALSE;
  644.         while(counter>newlen-12 && counter>=0 && escape==FALSE)
  645.         {
  646.                 if(temp[counter]=='\033')
  647.                 {
  648.                         escape=TRUE;
  649.                 }
  650.                 counter--;
  651.         }
  652.         counter2=counter;
  653.         counter2++;
  654.         while(counter2<newlen && escape==TRUE)
  655.         {
  656.                 counter2++;
  657.                 if((temp[counter2]>='A' && temp[counter2]<='Z')
  658.                         || (temp[counter2]>='a' && temp[counter2]<='z'))
  659.                 {
  660.                         escape=FALSE;
  661.                 }
  662.         }
  663.         if(escape==TRUE)
  664.         {
  665.                 strncat(charbuf, temp, counter);
  666.                 sendmessage(charbuf, 0);
  667.                 strmid(temp, charbuf, counter+1, newlen-counter+1);
  668.         }
  669.         else
  670.         {
  671.              strcat(charbuf, temp);
  672. /* Make sure the resultant string (Old character buffer with partial escape
  673.    sequence, and new string which doesn't have the start of a partial escape
  674.    sequence) isn't still a partial escape sequence, before printing it. If
  675.    the string is a partial escape sequence, leave it stored in the character
  676.    buffer for next time around */
  677.              counter=0;
  678.              newlen=strlen(charbuf);
  679.              while(counter<newlen)
  680.              {
  681.                 if(charbuf[counter]=='\033')
  682.                 {
  683.                    escape=TRUE;
  684.                    while(counter<newlen)
  685.                    {
  686.                       counter++;
  687.                       if((charbuf[counter]>='a' && charbuf[counter]<='z')
  688.                         || (charbuf[counter]>='A' && charbuf[counter]<='Z'))
  689.                       {
  690.                          escape=FALSE;
  691.                          break;
  692.                       }
  693.                    }
  694.                 }
  695.                 counter++;
  696.              }
  697.              if(escape==FALSE)
  698.              {
  699.                 sendmessage(charbuf, 0);
  700.                 strcpy(charbuf, "");
  701.              }
  702.         }
  703.  
  704. }
  705.  
  706. /* Strip CR's from string, plus a few other conversions!
  707.  */
  708. void convert_lf(char *buf, char *str, LONG len)
  709. {
  710.     LONG i, ii=0;
  711.     
  712.     for (i=0; i<len; i++)
  713.     {
  714.         buf[ii]=str[i];
  715. /* Stop Max's from converting special display sequences */
  716.                 if(buf[ii]=='|')
  717.                 {
  718.                         buf[ii+1]='\013';
  719.                         ii++;
  720.                 }
  721.                 if(buf[ii]=='@')
  722.                 {
  723.                         buf[ii+1]='\013';
  724.                         ii++;
  725.                 }
  726.                 if(buf[ii]=='%')
  727.                 {
  728.                         buf[ii+1]='\013';
  729.                         ii++;
  730.                 }
  731. /* Add in an extra escape for each escape character found */
  732.                 if(buf[ii]=='\033')
  733.                 {
  734.                         buf[ii+1]='\033';
  735.                         ii++;
  736.                 }
  737. /* Take out CR's */
  738.                 if (buf[ii]=='\r')
  739.                 {
  740.                         ii--;
  741.                 }
  742.         ii++;
  743.     }
  744.     buf[ii]='\0';
  745. }
  746.  
  747. /* Display command line usage */
  748.  
  749. void show_usage(void)
  750. {
  751.     printf("-- MAXShell v1.01 by MPS in 1995!\n");
  752.     printf("-- Based on the original TrShell by Tim Aston\n");
  753.     printf("-- M A X's BBS Remote Shell\n\n");
  754.     printf("Usage:\n\nMAXShell <startup-script> [-c] [-d] [-e] [-f] [-s<substitution char>] [-t]\n\n");
  755. }
  756.  
  757. /* Send a break.
  758.  */
  759. void SendBreak(char c)
  760. {
  761.     char buf[256];
  762.     LONG fh;
  763.  
  764.     sprintf(buf, "FIFO:%s/%c", fifoname, c);
  765.     if (fh = Open(buf, 1005))
  766.         Close(fh);
  767. }
  768.  
  769.  
  770. /* Cleanly and safely shutdown all resources.
  771.  */
  772.  
  773. void WaitMsg(struct Message *msg)
  774. {
  775.     while (msg->mn_Node.ln_Type == NT_MESSAGE)
  776.         Wait(1 << msg->mn_ReplyPort->mp_SigBit);
  777.     Forbid();
  778.     Remove(&msg->mn_Node);
  779.     Permit();
  780. }
  781.  
  782. main(int argc, char *argv[])
  783. {
  784.         /* char userstring[1000]; */
  785.         char linein[256], lineout[256], linestring[80];
  786.         long uservalue, savedflags;
  787.         int i, ii, j;
  788.     char buffer[81],line_number;
  789.     char cportname[12];    /* ReplyPort and Control Port names */
  790.         char infilename[80]="DOORS:MAXSHELL/";
  791.  
  792.     /* Pull out the line number from the argv field to find where we are */
  793.     
  794.     line_number=argv[argc-1][0];
  795.  
  796.     mytask=(struct Task *)FindTask('\0');
  797.     mytask->tc_Node.ln_Name = "DoorExample";
  798.  
  799.     /* Create the Reply port, with the name based on the number... */
  800.     
  801.     sprintf(buffer,"DoorReply%c",line_number);
  802.     replyport=(struct MsgPort *)CreatePort(buffer,0L);
  803.     
  804.     doormsg=(struct DoorMsg *)AllocMem((long)sizeof(*doormsg),MEMF_PUBLIC);
  805.     
  806.     if(doormsg==0)
  807.     {
  808.         puts("Couldn't allocate DoorMsg!");
  809.                 show_usage();
  810.         return;
  811.     }
  812.     
  813.     doormsg->Door_Msg.mn_Node.ln_Type = NT_MESSAGE;
  814.     doormsg->Door_Msg.mn_ReplyPort = replyport;
  815.     doormsg->Door_Msg.mn_Length = (UWORD)sizeof(*doormsg);
  816.     
  817.     /* Locate the correct DoorControl port based on the line number */
  818.     
  819.     sprintf(cportname,"DoorControl%c",line_number);
  820.        MyPort=(struct MsgPort *)FindPort(cportname);
  821.        if(MyPort==0L) 
  822.     {
  823.         puts("DoorControl port not located!");
  824.         FreeMem(doormsg,(long)sizeof(*doormsg));
  825.                 show_usage();
  826.         return;
  827.     }
  828.  
  829.     /* Parse command line switch arguments.
  830.      */
  831.  
  832.     for (i=1; i<argc; i++)
  833.     {
  834.         if (argv[i][0]=='-')
  835.         {
  836.             switch (argv[i][1])
  837.             {
  838.                 case 'c':
  839.                 case 'C':
  840.                     filterc=TRUE;
  841.                     break;
  842.                 case 'F':
  843.                 case 'f':
  844.                     filterf=TRUE;
  845.                     break;
  846.                 case 'D':
  847.                 case 'd':
  848.                     filterd=TRUE;
  849.                     break;
  850.                 case 'E':
  851.                 case 'e':
  852.                     filtere=TRUE;
  853.                     break;
  854.                                 case 's':
  855.                                 case 'S':
  856.                                         newchar=argv[i][2];
  857.                                         break;
  858.                                 case 'T':
  859.                                 case 't':
  860.                                         lesstime=TRUE;
  861.             }
  862.                 }
  863.     }
  864.  
  865. /* Open a CLI redirected to FIFO: based on an individual filename
  866.      generated from the system time (Hope it's not too long!) */
  867.  
  868. /* The same filename is also used for the names of the two FIFO's, opened
  869.    later */
  870.    
  871. timeval=time(timeptr);
  872. sprintf(fifoname, "%d_%c", timeval, line_number);
  873. strcat(commandline, fifoname);
  874. strcat(commandline, "/rwkecs");
  875. if(argc>2)
  876. {
  877.         /* Generate a new Shell-Startup script with proper autoinserts
  878.            (Name is based on the same FIFO: filename used above) */
  879.         strcat(infilename, argv[1]);
  880.         ifp=fopen(infilename, "r");
  881.         if(ifp==NULL)
  882.         {
  883.                 sendmessage("Can't open given startup script - Opening a standard shell.\r\n", 0);
  884.         }
  885.         else
  886.         {
  887.                 sprintf(newfile,"RAM:%s", fifoname);
  888.                 ofp=fopen(newfile, "w");
  889.                 while(fgets(linein, 256, ifp)!=NULL)
  890.                 {
  891.                    ii=0;
  892.                    for(i=0; i<strlen(linein);i++)
  893.                    {
  894.                       lineout[ii]=linein[i];
  895.                       if(lineout[ii]=='%')
  896.                       {
  897.                          i++;
  898.                          GetAutoInsert(linein[i], linestring);
  899.                          for(j=0; j<strlen(linestring); j++)
  900.                          {
  901.                             lineout[ii]=linestring[j];
  902.                             ii++;
  903.                          }
  904.                          ii--;
  905.                       }
  906.                       ii++;
  907.                    }
  908.                    lineout[ii]='\0';
  909.                    fprintf(ofp, "%s", lineout);
  910.                 }
  911.                 fclose(ifp);
  912.                 fclose(ofp);
  913.         /* ... and add the right stuff to the command line. */
  914.                 strcat(commandline," FROM ");
  915.                 strcat(commandline, newfile); /* Converted Shell-Startup script */
  916.         }
  917. }
  918. system(commandline);
  919.  
  920. /*
  921.         sendmessage(commandline,1);
  922.     sendmessage("\r\nHi there! Welcome to the test version of MAXShell\r\n",1);
  923.  
  924.         uservalue=getuserint(1);
  925.         sprintf(userstring, "The user's flags value: %ld\n", uservalue);
  926.         sendmessage(userstring, 0);
  927.  
  928.     hotkey("Press any key to (most likely) crash the computer...",buffer);    
  929. */
  930.  
  931. /* ofp2=fopen("ram:test", "w"); */
  932.  
  933. /* Set user's PAUSE flag to OFF, so the annoying 'Press Return' doesn't appear
  934.    all the time in scrolling text doors such as Hack & Slash (And the standard
  935.    shell). The user's previous flag value is saved for restoration before
  936.    returning back to the BBS */
  937.  
  938. uservalue=getuserint(108);
  939. savedflags=uservalue;
  940. uservalue&=0xffffff7fL; /* Turn bit 7 (Pause) of the user's flags OFF */
  941. changeuserint(13, uservalue);
  942.  
  943.     /* Open fifo.library.
  944.      */
  945.         FifoBase=OpenLibrary("fifo.library",0L);
  946.         if(!FifoBase)
  947.     {
  948.         printf("ERROR: Couldn't open fifo.library\n");
  949.  
  950. /* Temporary: I'll have to change this ... */
  951.  
  952.         exit(10);
  953.                 CloseLibrary(FifoBase);
  954.     }
  955.  
  956.     setup_fifo();
  957.     shell_loop();
  958.  
  959.     close_all();
  960.  
  961. /* Delete temporary shell-startup file... */
  962.  
  963.         strcpy(linein, "c:delete ");
  964.         strcat(linein, newfile);
  965.         system(linein);
  966.  
  967. /* Restore user's previous PAUSE flag setting */
  968.  
  969.         changeuserint(13, savedflags);
  970.  
  971. /* Close down the door... */
  972.  
  973. /* fclose(ofp2); */
  974.  
  975.         end();
  976.  
  977. }
  978.  
  979. void close_all(void)
  980. {
  981.     if (readpending)
  982.     {
  983.         RequestFifo(fifoR, &rmsg, FREQ_ABORT);
  984.         WaitMsg(&rmsg);
  985.     }
  986.     if (writepending)
  987.     {
  988.         RequestFifo(fifoW, &wmsg, FREQ_ABORT);
  989.         WaitMsg(&wmsg);
  990.     }
  991.     if (fifoR) CloseFifo(fifoR, FIFOF_EOF);
  992.     if (fifoW) CloseFifo(fifoW, FIFOF_EOF);
  993.     if (fifoport) DeletePort(fifoport);
  994.         if (FifoBase) CloseLibrary(FifoBase);
  995. }
  996.